﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using MbUnit.Framework;

namespace DeSleeper.Tests
{
    static class DependencyObjectExtensions
    {
        public static void AssertEqual(this DependencyObject expected, DependencyObject actual)
        {
            var expectedProperties = getProperties(expected);
            var actualProperties = getProperties(actual);
            Assert.AreElementsEqualIgnoringOrder(expectedProperties, actualProperties, compare);
        }

        public static bool Compare(this DependencyObject expected, DependencyObject actual)
        {
            var expectedProperties = getProperties(expected);
            var actualProperties = getProperties(actual);
            foreach (var pair in actualProperties)
            {
                if (!compare(pair.Value, expectedProperties[pair.Key])) return false;
            }
            return true;
        }

        private static bool compare(KeyValuePair<DependencyProperty, object> arg1, KeyValuePair<DependencyProperty, object> arg2)
        {
            if (arg1.Key != arg2.Key) return false;
            return compare(arg1.Value, arg2.Value);
        }

        private static bool compare(object arg1, object arg2)
        {
            if (arg1 == arg2) return true;
            if (arg1 == null || arg2 == null) return false;
            var dp1 = arg1 as DependencyObject;
            var dp2 = arg2 as DependencyObject;
            if (dp1 == null && dp2 == null) return arg1.Equals(arg2);
            return dp1.Compare(dp2);
        }


        private static Dictionary<DependencyProperty, object> getProperties(DependencyObject dp)
        {
            var properties = new Dictionary<DependencyProperty, object>();
            var enumerator = dp.GetLocalValueEnumerator();
            while (enumerator.MoveNext())
            {
                properties.Add(enumerator.Current.Property, enumerator.Current.Value);
            }
            return properties;
        }
    }
}
